package com.cherry.androidcode.demo

import com.cherry.androidcode.R
import com.cherry.androidcode.base.BaseActivity

/**
 * 未完待续https://blog.csdn.net/chengzichen_/article/details/77840996
 * @author DongMS
 * @since 2019/11/23
 */
class RetrofitOkhttpDemoActivity:BaseActivity() {
    /**
     * 1.请求方式注解
     * GET（SELECT）：从服务器取出资源（一项或多项）
    POST（CREATE）：在服务器新建一个资源。
    DELETE（DELETE）：从服务器删除资源。
    PUT（UPDATE）：在服务器更新资源（客户端提供改变后的完整资源）。
    PATCH（UPDATE）：在服务器更新资源（客户端提供改变的属性）。
    HEAD :获取资源的元数据。
    OPTIONS: 获取信息，关于资源的哪些属性是客户端可以改变的

    2.使用方法上部注解
    HTTP: 官方给出的定义:为请求使用定制的HTTP请求的注解
     ex:@HTTP(method = "yyy", path = "custom/endpoint/")
        Call<ResponseBody> xxx();
        @HTTP(method = "DELETE", path = "remove/", hasBody = true)
        Call<ResponseBody> deleteObject(@Body RequestBody object);
    FormUrlEncoded：请求主体将使用表单URL编码提交。用这个注释做的请求将有 application/x-www-form-urlencoded 的MIME类型
    Headers:请求头以固定方式直接添加到请求方法上
    ex:
    @Headers({"X-Foo: Bar","X-Ping: Pong"})
    @GET("user")
    Call<User> foo();

    Multipart：请求体是多部分的组成的。应该将部件声明为参数，带有@Part,并允许多个,一般用于多图文一起提交的情况
    ex:
    @Multipart
    @POST("register")
    Call<User> registerUser(@Part MultipartBody.Part photo, @Part("username") RequestBody username, @Part("password") RequestBody password);


    Streaming:将 返回结果转为byte[],如果下载一个非常大的文件，Retrofit会试图将整个文件读进内存。为了避免这种现象的发生，需要添加了一个特殊的注解来声明请求

    3.方法参数类使用的注解
    Url:URL将替换BaseUrl
    ex:  @GET
    Call<ResponseBody> xxx(@Url String url);

    Body：想要直接控制一个post/put请求的请求体时(而不是作为请求参数或表单样式的请求体发送)，在服务方法param上使用该注释
    需要创建一个Converter转换器,把需要提交的数据序列化以下,再放入body中去
    一般情况下GsonConverter支持了序列化为json的就够了,特殊情况只需要重写Converter就可以,当然也支持:
    Gson: com.squareup.retrofit2:converter-gson
    Jackson: com.squareup.retrofit2:converter-jackson
    Moshi: com.squareup.retrofit2:converter-moshi
    Protobuf: com.squareup.retrofit2:converter-protobuf
    Wire: com.squareup.retrofit2:converter-wire
    Simple XML: com.squareup.retrofit2:converter-simplexml
    ex:
    //这里是默认使用的GsonConverter,所以@Body 传TeamInviteRequestBean对象就可以转成Json
    @Headers({"Content-Type: application/json;charset=UTF-8","Accept: application/json"})//需要添加头
    @POST("group-rest/groupInvitation/push")
    Flowable<ApiResponse<String>> teamInvite(@Body TeamInviteRequestBean teamInviteRequestBean)

    Path:在URL路径段中指定的替换。值被转换为字符串和URL编码,(与Converter类中stringConverter方法有关,如果没有找到合适的转化器,将会使用Object的toString方法)
    ex:
    @GET("/image/{id}")
    Call<User> example(@Path("id") int id);

    Field:用于Post方式传递参数,需要在请求接口方法上添加@FormUrlEncoded,即以表单的方式传递参数
    ex:
    @FormUrlEncoded
    @POST("user/edit")
    Call<User> example(@Field("name") String name);

    FieldMap : 用于Post方式传递参数,需要在请求接口方法上添加@FormUrlEncoded,即=以表单编码的请求命名的键/值对
    ex:
    @FormUrlEncoded
    @POST("user/edit")
    Call<User> things(@FieldMap Map<String, String> fields);

    Header
    HeaderMap
    ex:
    @GET("user")
    Call<User> foo(@Header("Authorization") String authorization)
    GET("/search")
    Call<User> foo()(@HeaderMap Map<String, String> headers);

    Part:表示多部分请求的单个部分
    ex:
    @Multipart
    @POST("/")
    Call<ResponseBody> example(@Part("description") String description,@Part(value = "image", encoding = "8-bit") RequestBody image);
    PartMap:表示多部件请求的名称和值部分。同@Part是样的,只是以Map键值对形式提交,作为键或值是不允许的null的
    ex:
    @Multipart
    @POST("/upload")
    Call<ResponseBody> upload(@Part("file") RequestBody file,@PartMap Map<String, RequestBody> params)

    Query
    QueryMap
    用于Http Get请求传递参数 :类似拼接问号后面一段: http://www.xxx.com/user?username=zhangsan
    ex:
    @GET("group/users")
    Call example(@Query("user") int userId);
    @GET("/group/{id}/users")
    List<USer> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

    QueryName
    用于Http Get请求没有值的传递参数 :类似拼接问号后面一段: http://www.xxx.com/user?username&password
    ex:
    @GET("/friends")
    Call<ResponseBody> friends(@QueryName String filter);
    @GET("/friends")
    Call<ResponseBody> friends(@QueryName String... filters);// Array/Varargs:多个

    Call方法：Call实现类一个OkHttpCall
    execute() :同步执行请求
    enqueue() :异步执行请求
    cancel() :取消当前请求
    clone() :克隆当前请求

    //.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    CallAdapter：最终处理OkHttpCall实例并返回接口Method, 用来适配Rxjava,Java8,Guava等等
            Type responseType()：通过ParameterizedType获取java泛型参数类型,也就是获取response返回参数的类型
            T adapt(Call<R> call)：将传进来的call转化为对应的类型,比如转成:rxjava需要的Flowable或者Observable
            CallAdapter.Factory
            DefaultCallAdapterFactory :对 CallAdapter.Factory实现类,默认的
            ExecutorCallAdapterFactory : (重点:装饰模式,工厂模式)ExecutorCallbackCall是用来切换线程和调用okhttpCall方法,调用okhttpCall与okhttp打交道

    //.addConverterFactory(GsonConverterFactory.create())
    类中，List<Converter.Factory> converterFactories，可以添加多个，从前往后匹配，当factory.requestBodyConverter返回空时，表示没有匹配上，可使用下一个factory，所以需要在factory.requestBodyConverter针对条件限制
    Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit)
    可以在方法或者参数上添加自定义注解或者判断Type类型进行转换器的条件选择

    Converter：转化器,就是提供responseBody,responseBody的转换的接口,也就是说在处理结果请求前和后都能分别对请求参数和请求结果进行合理的改变
        Converter<ResponseBody, ?> responseBodyConverter() //请求后对结果进行解析或者解密等操作,可以参考 GsonResponseBodyConverter
        Converter<?, RequestBody> requestBodyConverter()//请求前对请求参数进行格式化(比如格式化为Json格式)或者加密,可以参考 GsonRequestBodyConverter
        Converter.Factory
        BuiltInConverters : 是Retrofi默认的转化器 ,默认responseBodyConverter返回结果为Buffer,也可以用@Streaming注解设置为Streaming类型

     *
     */


    override val activityLayoutRes = R.layout.activity_retrofit_okhttp_demo
}